package br.edu.fasete.javaroad.plugin.amateras;

import java.awt.event.FocusAdapter;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.JScrollPane;
import javax.swing.JTable;

import net.java.amateras.uml.classdiagram.model.ClassModel;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.FolderSelectionDialog;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;

import br.edu.fasete.javaroad.log.LogManager;
import br.edu.fasete.javaroad.model.EntityDescriptor;
import br.edu.fasete.javaroad.model.EntityList;
import br.edu.fasete.javaroad.model.architeture.Architeture;
import br.edu.fasete.javaroad.model.architeture.ArchitetureIO;
import br.edu.fasete.javaroad.plugin.ProjectConfigurations;
import br.edu.fasete.javaroad.plugin.gui.tablemodel.ClassTableModel;

public class WizardPageArquitetura extends WizardPage {
	private IJavaProject project;
	private Map target = new HashMap();

	private Text srcdir;
	private Text basePackage;
	private Text architeture;
	private JScrollPane scrollTabela;
	private JTable listClasses = null;
	private ClassTableModel modelo = null;

	private ProjectConfigurations configurations;
	
	public WizardPageArquitetura(IJavaProject project, Map target, ProjectConfigurations configurations) {
		super("Output Folder");
		setTitle("Select an Architeture");
		this.project = project;
		this.target = target;
		this.configurations = configurations;
	}

	public boolean isPageComplete() {
		if(configurations.getArchiteture() != null &&
				!basePackage.getText().trim().equals("") &&
				target.size() != 0) 
			return true;
		else 			
			return false;
	}

	public void setVisible(boolean v) {
		if(!v) {
			configurations.setListaClasses(modelo.getListClass());
			configurations.setProjectRoot(srcdir.getText());
			configurations.setPacote(basePackage.getText());
			String path = project.getProject().getLocation().toOSString();
			configurations.setProjectPath(path);
		}
		super.setVisible(v);
	}

	public void createControl(Composite parent) {
		getShell().setText("Project Generation");

		Composite composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout(3, false));
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));

		Label label = new Label(composite, SWT.NULL);
		label.setText("Output Folder:");
		srcdir = new Text(composite, SWT.BORDER);
		srcdir.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		Button button = new Button(composite, SWT.PUSH);
		button.setText("...");
		button.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				selectFolder();
				getContainer().updateButtons();
			}
		});
		
		
		label = new Label(composite, SWT.NULL);
		label.setText("Base Package:");
		basePackage = new Text(composite, SWT.BORDER);
		GridData dg1 = new GridData(GridData.FILL_HORIZONTAL);
		dg1.horizontalSpan = 2;
		basePackage.setLayoutData(dg1);
		basePackage.addFocusListener(
				new FocusListener() {
					public void focusLost(FocusEvent arg0) {
						if(!basePackage.getText().trim().equals("")) {
							configurations.setPacote(basePackage.getText().trim());
							getContainer().updateButtons();
						}
					}

					public void focusGained(FocusEvent arg0) { }
				}
		);


		label = new Label(composite, SWT.NULL);
		label.setText("Architeture:");
		architeture = new Text(composite, SWT.BORDER);
		architeture.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		architeture.setEditable(false);
		Button button2 = new Button(composite, SWT.PUSH);
		button2.setText("...");
		button2.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				selectArchiteture();
				getContainer().updateButtons();
			}
		});


		label = new Label(composite, SWT.NULL);
		label.setText("Choose Entities:");
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 3;
		label.setLayoutData(gd);


		Composite tableComp = new Composite(composite, SWT.EMBEDDED);
		gd = new GridData(GridData.FILL_BOTH);
		gd.horizontalSpan = 3;
		tableComp.setLayoutData(gd);
		java.awt.Frame fileTableFrame = SWT_AWT.new_Frame(tableComp);
		java.awt.Panel panel = new java.awt.Panel(new java.awt.BorderLayout());
		fileTableFrame.add(panel);
		panel.add(getScrollTabela());

		try {
			IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
			for(int i=0;i<roots.length;i++){
				IResource classpath = roots[i].getResource();
				if(classpath!=null && (classpath instanceof IFolder || classpath instanceof IProject)){
					srcdir.setText(classpath.getProjectRelativePath().toString());
					break;
				}
			}
		} catch(Exception ex){	}

		setControl(composite);
	}

	private void selectFolder() {
		try {
			IProject currProject = project.getProject();
			IResource init = null;
			if(!srcdir.getText().equals("")){
				init = currProject.findMember(srcdir.getText());
			}
			Class[] acceptedClasses = new Class[] { IProject.class, IFolder.class };
			ISelectionStatusValidator validator = new TypedElementSelectionValidator(acceptedClasses, false);

			IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
			IProject[] allProjects = wsroot.getProjects();

			ArrayList rejectedElements = new ArrayList(allProjects.length);
			for (int i = 0; i < allProjects.length; i++) {
				if (!allProjects[i].equals(currProject)) {
					rejectedElements.add(allProjects[i]);
				}
			}
			ViewerFilter filter = new TypedViewerFilter(acceptedClasses, rejectedElements.toArray());

			FolderSelectionDialog dialog = new FolderSelectionDialog(
					getShell(),
					new WorkbenchLabelProvider(), 
					new WorkbenchContentProvider());

			dialog.setTitle("Select output folder");
			dialog.setMessage("Select output folder:");

			dialog.setInput(wsroot);
			dialog.setValidator(validator);
			dialog.addFilter(filter);
			dialog.setInitialSelection(init);
			if (dialog.open() == Window.OK) {
				srcdir.setText(getFolderName(dialog.getFirstResult()));
			}

		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	private void selectArchiteture() {
		FileDialog fileDialog = new FileDialog(getShell(), SWT.MULTI);
		fileDialog.setFilterExtensions(new String[]{"*.jor"});
		fileDialog.setFilterNames(new String[]{ "Java On Road Architeture File"});
		String firstFile = fileDialog.open();

		if(firstFile != null) {
			String selectedFile = fileDialog.getFileName();
			String sb = fileDialog.getFilterPath() +  "/";
			sb = sb + selectedFile;
			architeture.setText(sb);

			File arq = new File(sb); 
			if(arq.exists()) {
				Architeture arc = ArchitetureIO.loadArchiteture(arq);
				configurations.setArchiteture(arc);
			}
		}
	}

	private String getFolderName(Object result) throws CoreException {
		if (result instanceof IFolder) {
			IFolder folder = (IFolder) result;
			return folder.getProjectRelativePath().toString();
		}
		return "";
	}


	public void carregarTabela() {
		modelo.limparTabela();

		Iterator ite = target.keySet().iterator();
		while(ite.hasNext()){
			String element = ite.next().toString();
			if(target.get(element) instanceof ClassModel) {
				modelo.adicionarClasse(element, true, true);
			} else {
				modelo.adicionarClasse(element, false, false);
			}
				
		}
	}

	public JScrollPane getScrollTabela() {
		if(scrollTabela == null) {
			modelo = new ClassTableModel();
			listClasses = new JTable(modelo);
			scrollTabela = new JScrollPane();
			scrollTabela.setViewportView(listClasses);
			carregarTabela();
		}
		return scrollTabela;
	}

}
